iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Software Development

系統設計就像九頭蛇:打造社群網站的 30 天系列 第 5

Day 5 一台 Server 不夠用:Vertical Scaling vs Horizontal Scaling

  • 分享至 

  • xImage
  •  

這幾天我們把最陽春的 PokeThreads 做出來了,也解決了 Feed 該回傳什麼內容的問題,但整個架構其實還停留在最原始的狀態:

瀏覽器 -> Server -> Database

只有一台 Server,所有使用者的 Request 都打到同一個地方。當時的假設是使用者只有 100 人,這台 Server 綽綽有餘,但如果使用者從 100 人變成 10 萬人、100 萬人呢?

即使 Database 還撐得住,這一台 Server 本身的運算能力終究有極限,於是我們要面對一個很基本、卻也很重要的問題:

當一台 Server 不夠用了,我們該怎麼辦?

把 Server 變強

假設現在的 Server 規格是:

  • 4 CPU
  • 8 GB RAM

流量增加時,最直接的想法就是換一台更強的機器

  • 16 CPU
  • 64 GB RAM

這種做法叫做 Vertical Scaling(垂直擴展),也稱為 Scale Up

它最大的優點是完全不用改架構

原本:瀏覽器 -> Server      -> Database
現在:瀏覽器 -> 更強的 Server -> Database

不需要處理 Request 該分配到哪一台,也不用多準備任何新元件。

自助餐裝不下?盤子加大就對了,就是這麼簡單粗暴。

對早期的小型系統來說,這其實是很合理的第一步。

Vertical Scaling 的問題

但 Vertical Scaling 有兩個很明顯的天花板。

第一,硬體有極限。CPU、Memory 不可能無限往上疊,即使雲端廠商能提供非常誇張規格的機器,也不代表我們能無限制地升級下去。

第二,也是更關鍵的一個問題:Single Point of Failure(單點故障)

現在所有 Request 都由這一台 Server 處理,可是一旦它當機,不管是網路問題、硬體故障還是 OS 出包,所有使用者都會連不上我們的服務,整個網站直接烙賽,SRE 頭殼𢯾咧燒。

就算這台 Server 效能再好,只要世界上只有一台,風險就一直都在。

增加 Server 的數量

既然把單一機器越養越大會撞到天花板,那換個方向:不要只養一隻大的,改養一群。

原本只有:

Server 1

現在變成:

Server 1
Server 2
Server 3

這就是 Horizontal Scaling(水平擴展),也叫 Scale Out

但問題馬上就來了:現在有三台 Server,使用者的 Request 到底該送去哪一台?

Load Balancer 幫助分流

這時候需要引入一個新元件:Load Balancer(負載平衡器)

可以把它想成銀行大廳的號碼牌機,客人(Request)進門先抽號碼牌,系統再把客人平均分配給空著的櫃檯(Server),客人不需要知道今天有幾位櫃員在上班,只要跟著號碼牌走就好。

Load Balancer 放在 Client 與 Application Server 之間:

Load Balancer 放在 Client 與 Application Server 之間的架構圖

使用者只知道自己連上了「一個服務」,DNS 解析到的其實是 Load Balancer 的位址,實際上背後有幾台 Server 在工作,對使用者來說是透明的。

最簡單的分配方式:Round Robin

假設現在有 Server A、B、C,最直覺的分配方式是輪流發放號碼牌:

Request 1 → Server A
Request 2 → Server B
Request 3 → Server C
Request 4 → Server A
Request 5 → Server B
Request 6 → Server C

這種做法就是 Round Robin,既簡單又公平,是很多 Load Balancer 的預設策略。

Health Check:不能把客人排到打烊的櫃檯

銀行號碼牌機還有一個很重要的功能:如果某個櫃檯的行員臨時離開,系統不會再把新客人分配過去。

Load Balancer 也是一樣的邏輯,它會定期對每一台 Server 送出 Health Check(健康檢查),確認對方是否還活著、是否還能正常處理 Request。

假設 Server B 掛掉了:

Browser
   ↓              ┌── Server A ✓
Load Balancer ────┼── Server B ✗
                  └── Server C ✓

Load Balancer 一旦偵測到 Server B 沒有回應,就會停止把新 Request 導向它,直到它恢復正常為止。這讓系統具備了初步的 Fault Tolerance(容錯能力),少了一台 Server,服務還是能繼續運作,只是整體處理能力會下降。

現在的架構

加上 Load Balancer 和多台 Server 之後,架構從最初的樣子:

瀏覽器 -> Server -> Database

演化成:

瀏覽器 -> Load Balancer -> Server(多台)-> Database

具體來說,我們現在具備了:

  • 多台 Application Server
  • Load Balancing
  • Health Check
  • 初步的 Fault Tolerance

Vertical Scaling vs Horizontal Scaling

把兩種擴展方式放在一起比較:

Vertical Scaling Horizontal Scaling
做法 把機器變強 增加機器數量
別名 Scale Up Scale Out
架構複雜度 較高(需要 Load Balancer)
擴展上限 受硬體限制 可持續增加節點
Fault Tolerance 較弱(單點故障) 較容易做到
適合場景 小型、早期系統 高流量、大型系統

要提醒的是,這不是「Horizontal Scaling 永遠比較好」的結論。

實務上兩者經常一起使用,例如先把單台 Server 規格拉到一個合理甜蜜點,再用多台這種規格的機器做水平擴展。

真正該問的問題從來不是「哪一種比較好」,而是現在的瓶頸,需要哪一種擴展方式來解決

小結

今天解決的是 Application Server 這一層的擴展問題,但這裡其實埋了一個還沒拆開的細節。

回想 Day 2,我們是把使用者的登入狀態(Session)直接存在 Server 的 Memory 裡。

現在 Server 從一台變成了三台,如果 Pikachu 的第一個 Request 被分配到 Server A,第二個 Request 卻被分配到 Server B,而 Server B 的 Memory 裡根本沒有 Pikachu 的 Session,它還認得出這是誰嗎?

這是明天要處理的問題。


上一篇
Day 4 REST vs GraphQL:前後端到底該怎麼聊天?
下一篇
Day 6 Session 要放哪?
系列文
系統設計就像九頭蛇:打造社群網站的 30 天10
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言